package com.fyl.security.aop;

import com.fyl.core.advance.constant.IResponseEnum;
import com.fyl.core.advance.constant.enums.CommonResponseEnum;
import com.fyl.security.anno.OAuthPass;
import com.fyl.security.service.OAuthService;
import com.fyl.utils.ResponseUtil;
import org.aopalliance.intercept.MethodInterceptor;
import org.aopalliance.intercept.MethodInvocation;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy;
import org.springframework.core.annotation.AnnotationUtils;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.lang.annotation.Annotation;
import java.lang.reflect.Method;
import java.util.Objects;

public class OAuthMethodInterceptor implements MethodInterceptor {

    @Autowired
    HttpServletRequest request;

    @Autowired
    HttpServletResponse response;

    @Lazy
    @Autowired
    OAuthService oauthService;

    @Override
    public Object invoke(MethodInvocation invocation) throws Throwable {
        boolean preCheckResult = oauthService.preCheckHandler(request);
        boolean oauthPass = null == this.getAnnotation(invocation, OAuthPass.class);

        if (preCheckResult && oauthPass) {
            IResponseEnum responseEnum = oauthService.doCheckHandler(request);
            if (!Objects.equals(CommonResponseEnum.SUCCESS, responseEnum)) {
                ResponseUtil.cutResponse(responseEnum, response);
                return null;
            }
        }

        Object result = invocation.proceed();

        if (preCheckResult && oauthPass) {
            oauthService.postCheckHandler(response);
        }
        return result;
    }

    private Annotation getAnnotation(MethodInvocation methodInvocation, Class<? extends Annotation> annotationClass) {
        Method method = methodInvocation.getMethod();
        Annotation annotation = method.getDeclaredAnnotation(annotationClass);
        if (null != annotation) {
            return annotation;
        }
        Class<?> clazz = methodInvocation.getThis().getClass();
        return AnnotationUtils.getAnnotation(clazz, annotationClass);
    }

}
